<!doctype html>
    <head>
        <title>Informe - Arquitectura del Computador</title>
        <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    </head>
<body>

<h1>Informe sobre laboratorio OpenCL</h1>

<p><b>Estudiantes:</b>
    <br>Rossi Nahuel E-mail: nahuelr@live.com,
    <br>Moine Joaquin E-mail: joaquinmoine@gmail.com</p>

<h2>Decisiones de arquitectura adoptadas</h2>

<h3>Sincronismo</h3>
<p>Se sincroniza el los threads con barreras. Todos los kernels necesitan el valor de sus vecinos actualizados en el ciclo anterior. Lo que hace que todos estén interrelacionados con sus vecinos. Para evitar que se lea un dato de otro ciclo se regulan las escrituras/lecturas, de esta manera se efectúan en el momento correcto.</p>

<h3>Kernel</h3>
<p>La dimensión del workgroup es N*N, donde N*N es la dimensión del arreglo de la matriz de entrada. Esto transforma un calculo de:<br>
    <code class="codeblock">
    O(N*N*(complejidad de actualizar las temperaturas))<br>
    </code>
    a uno de :<br>
    <code class="codeblock">
    O((complejidad de actualizar las temperaturas))<br>
    </code>
    en contrapartida, con este diseño no se pueden calcular matrices que sean mayores a máximo work-items.</p>

<p>Una opción de diseño para trabajar con matrices mas grandes es asignarles mas elementos a cada kernel. Por ejemplo cada kernel podría calcular la posición:<br><br></p>
<div>
    <table border="1px" align="center"><tr><td>
        <code class="codeblock">
            int i=0;<br>
            int col get_global_id(0);<br>
            int row = get_global_id(1);<br><br>
            while(i*maxGroupSize + row*N + col < N*N){<br>
            &nbsp;&nbsp;actualizarTemperatura(i*maxWorkitems + row*N + col);<br>
            }<br>
        </code>
</td></tr></table></div>
<p>De esta manera cuando se acabaron los threads para calcular los elementos de la matriz 1 a 1, se le empiezan a asignar mas
    elementos a cada thread hasta que se haya completado la matriz. El orden del programa varia un poco.
    Es de <br><code>O(ceil(N*N/maxWorkitems)*(complejidad de actualizar las temperaturas))</code>.<br> Aunque si se cumple<br>
    <code>N*N>maxWorkitems</code><br> entonces el orden de los dos códigos es igual.
</p>
<p>En nuestro código se opto por que todos los work-items pertenezcan al mismo work-group</p>
<IMG SRC="kernelFlujo.png" align="right" WIDTH=400 HEIGHT=800>

<h3>Modelado del problema</h3>
<p>Para cada elemento de la matriz se calcula el valor de la k-esima iteración con el promedio de sus vecinos en la iteración k-1. Para luego actualizarce cuando se haya calculado todos los elementos. Se utiliza una barrera para lograr esto.</p>

<h3>Barreras</h3>
<p>Dentro de kernel.cl hay 4 barreras</p>
<p><b>Barrera 1:</b> Se utiliza para llenar por primera vez la matriz con las fuentes de calor, los primeros j (j=cantidad de fuentes de calor) items son los encargados de realizar esta tarea. Hasta que esto no se termine no se puede entrar al while.</p>
<p><b>Barrera 2:</b> Una vez que cada item realiza el calculo de su nuevo valor se agrega una nueva barrera, es incorrecto escribir directamente
    luego de calcular porque otro thread podria no haber leido todavia el valor generando una race condition.</p>
<p><b>Barrera 3:</b> una vez que se calcularon todos los nuevos valores se pueden escribir. Luego de esto se tiene que actualizar
    las fuentes de calor. Hasta que no se escriban todos los nuevos valores no se pueden actualizar.</p>
<p><b>Barrera 4:</b> Una vez actualizada toda la matriz, re pisan los valores de las fuentes de calor a su valor original. Se tiene que esperar a
    reescribir todas las fuentes para poder empezar otro ciclo. De no ser asi se corre el riesgo que se lea una temperatura de una fuente de
    calor antes de haber sido actualizada.</p>

<h3>Formatos de entrada/salida</h3>
<p>Se leen de la entrada el modo, la dimensión, la cantidad de iteraciones y las fuentes de calor. Estas ultimas son guardadas internamente en tres arreglos, el primero llamado X, que contiene los puntos X de las fuentes de calor, el segundo Y, que contiene los puntos Y de las fuentes de calor, y el tercero T, que contiene la temperatura.</p>
<p>La salida es impresa en formato %.2f, se imprime toda una fila por línea.</p>
<h2>Cuestiones de performance</h2>

<h3>Modo Express vs. Modo Real-Time</h3>

<p>
    En el modo Express se arma un kernel y se ejecuta una vez con <code>k</code>  iteraciones en el device. Por otro lado, en el modo Real-Time
    se arma el kernel y se manda a ejecutar <code>k</code> veces. Esto implica un consumo de recursos extra ya que aumenta la comunicación
    <code>Host-Device</code>.<br>
    Ayudando a aumentar esta diferencia, en el modo Real-Time se quiere obtener el resultado de cada iteración, agregando etapas de comunicación
    para obtener los datos, etapas en la cual el device no puede operar por que podría generar condiciones de carrera.<br>
    Tambien el modo Real-Time tiene impresiones en pantalla en cada iteración lo que lo transforma en un programa Input/Ouput Bound.<br>
    Por lo expuesto es que el modo Express tiene un rendimiento altísimo comparado con el Real-Time.
</p>

<h3>Utilización de un solo kernel para los dos modos</h3>
<p>Una ventaja de tener un solo kernel es que simplifica el diseño. De esta manera se cumple con el principio DRY(Don't Repeat Yourself).<br>
    La desventaja es que en el modo real time hay mas barreras de las necesarias y el bucle while es innecesario. Pero no repercute de manera
    significativa en el performance de la aplicación.

</p>

<h3>Cuestiones a discutir</h3>

<h4>Performance</h4>
<p>Al analizar los tiempos devueltos en los dos modos se puede comprobar que es mas rápido el modo Real-Time debido es mas eficiente realizar k iteraciones dentro
    del kernel que k iteraciones en el host. Por este motivo también se elije setear las fuentes de calor dentro del kernel. Así esta operación es de <code>O(1)
    </code> y no de <code>O(j)</code> siendo <code>j</code> la cantidad de fuentes de calor.
</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

</body>
</html>